---
id: circular
title: Circular
sidebar_label: Circular
description: Circular animation
keywords:
  - custom-animations
  - circular
  - carousel animation
  - carousel animation circular
  - react-native-reanimated-carousel
  - reanimated-carousel
  - reanimated carousel
  - react-native
  - snap-carousel
  - react native
  - snap carousel
  - ios
  - android
  - carousel
  - snap
  - reanimated
image:
slug: /examples/custom-animations/circular
---

{/* 

=========================================================================
=========================================================================
This page generated by /scripts/gen-pages.mjs, Don't update it manually 
=========================================================================
=========================================================================

*/}

import { Tabs } from 'nextra/components'
import { Callout } from 'nextra/components'
import Demo from '@/components/Demo'

<Callout type="info" emoji="💡">
  Check out the `circular` animation demo for the full source code [here](https://github.com/dohooo/react-native-reanimated-carousel/blob/main/example/app/app/demos/custom-animations/circular/index.tsx)
</Callout>

<Demo kind="custom-animations" name="circular" />

```tsx copy
import * as React from "react";
import { View } from "react-native";
import { TouchableWithoutFeedback } from "react-native-gesture-handler";
import { interpolate } from "react-native-reanimated";
import Carousel, { TAnimationStyle } from "react-native-reanimated-carousel";

import { SlideItem } from "@/components/SlideItem";
import { window } from "@/constants/sizes";
import { getImages } from "@/utils/get-images";

const PAGE_WIDTH = window.width;

function Index() {
	const itemSize = 80;
	const centerOffset = PAGE_WIDTH / 2 - itemSize / 2;

	const animationStyle: TAnimationStyle = React.useCallback(
		(value: number) => {
			"worklet";

			const itemGap = interpolate(
				value,
				[-3, -2, -1, 0, 1, 2, 3],
				[-30, -15, 0, 0, 0, 15, 30],
			);

			const translateX =
				interpolate(value, [-1, 0, 1], [-itemSize, 0, itemSize]) +
				centerOffset -
				itemGap;

			const translateY = interpolate(
				value,
				[-1, -0.5, 0, 0.5, 1],
				[60, 45, 40, 45, 60],
			);

			const scale = interpolate(
				value,
				[-1, -0.5, 0, 0.5, 1],
				[0.8, 0.85, 1.1, 0.85, 0.8],
			);

			return {
				transform: [
					{
						translateX,
					},
					{
						translateY,
					},
					{ scale },
				],
			};
		},
		[centerOffset],
	);

	return (
		<View
			id="carousel-component"
			dataSet={{ kind: "custom-animations", name: "circular" }}
		>
			<Carousel
				width={itemSize}
				height={itemSize}
				style={{
					width: PAGE_WIDTH,
					height: PAGE_WIDTH / 2,
				}}
				loop
				data={getImages(12)}
				renderItem={({ index }) => (
					<TouchableWithoutFeedback
						key={index}
						onPress={() => {
							console.log(index);
						}}
						containerStyle={{ flex: 1 }}
						style={{ flex: 1 }}
					>
						<View
							style={{
								backgroundColor: "white",
								flex: 1,
								borderRadius: 50,
								justifyContent: "center",
								overflow: "hidden",
								alignItems: "center",
							}}
						>
							<View style={{ width: "100%", height: "100%" }}>
								<SlideItem index={index} />
							</View>
						</View>
					</TouchableWithoutFeedback>
				)}
				customAnimation={animationStyle}
			/>
		</View>
	);
}

export default Index;

```